#ifndef _WX_EVTLOOP_H_
#define _WX_EVTLOOP_H_

#include "wx/utils.h"

class wxEventLoop;

class wxEventLoopBase {
  public:
    wxEventLoopBase() { }
    virtual ~wxEventLoopBase() { }
    virtual int Run() = 0;
    virtual void Exit( int rc = 0 ) = 0;
    virtual bool Pending() const = 0;
    virtual bool Dispatch() = 0;
    static wxEventLoop *GetActive() { return ms_activeLoop; }
    static void SetActive( wxEventLoop* loop ) { ms_activeLoop = loop; }
    bool IsRunning() const;
  protected:
    virtual void OnExit() { }
    static wxEventLoop *ms_activeLoop;
    DECLARE_NO_COPY_CLASS( wxEventLoopBase )
};

class wxEventLoopImpl;

class wxEventLoop : public wxEventLoopBase {
  public:
    wxEventLoop() { m_impl = NULL; }
    virtual ~wxEventLoop();
    virtual int Run();
    virtual void Exit( int rc = 0 );
    virtual bool Pending() const;
    virtual bool Dispatch();
  protected:
    wxEventLoopImpl *m_impl;
    DECLARE_NO_COPY_CLASS( wxEventLoop )
};

inline bool wxEventLoopBase::IsRunning() const { return GetActive() == this; }

class wxModalEventLoop : public wxEventLoop {
  public:
    wxModalEventLoop( wxWindow *winModal ) {
      m_windowDisabler = new wxWindowDisabler( winModal );
    }
  protected:
    virtual void OnExit() {
      delete m_windowDisabler;
      m_windowDisabler = NULL;
      wxEventLoop::OnExit();
    }
  private:
    wxWindowDisabler *m_windowDisabler;
};

class wxEventLoopActivator {
  public:
    wxEventLoopActivator( wxEventLoop *evtLoop ) {
      m_evtLoopOld = wxEventLoop::GetActive();
      wxEventLoop::SetActive( evtLoop );
    }
    ~wxEventLoopActivator() {

      wxEventLoop::SetActive( m_evtLoopOld );
    }

  private:
    wxEventLoop *m_evtLoopOld;
};

class wxEventLoopGuarantor {
  public:
    wxEventLoopGuarantor() {
      m_evtLoopNew = NULL;
      if( !wxEventLoop::GetActive() ) {
        m_evtLoopNew = new wxEventLoop;
        wxEventLoop::SetActive( m_evtLoopNew );
      }
    }

    ~wxEventLoopGuarantor() {
      if( m_evtLoopNew ) {
        wxEventLoop::SetActive( NULL );
        delete m_evtLoopNew;
      }
    }

  private:
    wxEventLoop *m_evtLoopNew;
};

#endif
